package hsintiao.com.xintiaoAPP.controller;


import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import hsintiao.com.xintiaoAPP.annotation.PassToken;
import hsintiao.com.xintiaoAPP.config.AlipayConfig;
import hsintiao.com.xintiaoAPP.entity.PayBill;
import hsintiao.com.xintiaoAPP.entity.User;
import hsintiao.com.xintiaoAPP.entity.single.AlipayGet;
import hsintiao.com.xintiaoAPP.entity.single.AlipayInfo;
import hsintiao.com.xintiaoAPP.service.PayBillService;
import hsintiao.com.xintiaoAPP.service.TestService;
import hsintiao.com.xintiaoAPP.service.UserService;
import hsintiao.com.xintiaoAPP.util.AjaxResult;
import hsintiao.com.xintiaoAPP.util.ResponseCode;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.ZipInputStream;

/*
* 支付宝接口
* */
@RestController
@RequestMapping("/alipay")
public class AlipayController {
    @Autowired
    private PayBillService payBillService;
    @Autowired
    private UserService userService;


    /*
    * 生成支付宝参数供app使用
    * */
    @PostMapping("/dopay")
    @ResponseBody
    @PassToken
    public AlipayInfo doPay(@RequestBody AlipayGet alipayGet, HttpServletResponse httpResponse) throws IOException {
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id,
                AlipayConfig.merchant_private_key, "json", "UTF-8",
                AlipayConfig.alipay_public_key, "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        Long goodID = alipayGet.getGoodID();
        Long userID = alipayGet.getUserID();
        //根据选择的商品id和用户id生成唯一订单
        PayBill payBill = payBillService.creatBill(goodID,userID);
        /*
        * 设置支付宝相关参数(商品名称、订单号等)
        * */
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(payBill.getItemName());
        model.setSubject(payBill.getItemName());
        model.setOutTradeNo(payBill.getOut_trade_no());
        model.setTimeoutExpress("30m");
        //将金额转换为小数(数据库以分为单位，除以100，获得以元为单位的小数金额)
        Double b1 = Double.valueOf(payBill.getTotal_amount());
        Double total_amount = b1 / 100;
        model.setTotalAmount(total_amount.toString());
        model.setProductCode("QUICK_MSECURITY_PAY");
        model.setPassbackParams(payBill.getUserId().toString());
        request.setBizModel(model);
        request.setNotifyUrl(AlipayConfig.notify_url);
        //String form ="";
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            String body = response.getBody();
            String s = body.substring(44);
            System.out.println(s);//就是orderString 可以直接给客户端请求，无需再做处理。
            //应前端要求封装成对象传递
            AlipayInfo alipayInfo = new AlipayInfo();
            //将支付宝sdkExecute封装的参数设置到对象中
            alipayInfo.setInfo(body);
            return alipayInfo;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /*
    * 异步回调
    * */
    @PostMapping("/notifyUrl")
    @ResponseBody
    public void notify_url(HttpServletRequest request,HttpServletResponse response) throws ParseException, IOException {
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        System.out.println("回调通知参数="+params);
        //切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean signVerified = false;
        try {
            signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, "UTF-8","RSA2");
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //获取相关参数
        String out_trade_no = params.get("out_trade_no");//商品订单号
        String total_amount = params.get("total_amount");//订单金额
        String receipt_amount = params.get("receipt_amount");//实际收到金额
        String subject = params.get("subject");//订单商品名称
        String buyer_id = params.get("buyer_id");
        String gmt_create = params.get("gmt_create");//订单创建时间
        String gmt_payment = params.get("gmt_payment");//支付时间
        String trade_status = params.get("trade_status");//交易状态
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:ss:mm");
        Date creatTime = format.parse(gmt_create);//订单创建时间
        Date payTime = format.parse(gmt_payment);//订单支付时间
        String seller_id = params.get("seller_id");//商户id
        String buyer_logon_id = params.get("buyer_logon_id");
        String app_id = params.get("app_id");//支付宝应用id
        String trade_no = params.get("trade_no");//支付宝订单号
        String userID1 = params.get("passback_params");//userID
        Long userID = this.getUserID(out_trade_no);

        System.out.println("用户id="+userID1+",或="+userID);

        if (signVerified){
            /*String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");


            System.out.println("out_trade_no="+out_trade_no+",trade_no="+trade_no+",trade_status="+trade_status);*/
            if(trade_status.equals("TRADE_FINISHED")){
                System.out.println("订单支付完成，进入数据库修改套餐状态");
                System.out.println("不可以进行退款");
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            }else if (trade_status.equals("TRADE_SUCCESS")){
                System.out.println("订单支付完成，进入数据库修改状态");
                System.out.println("可以进行退换==退款");
                PayBill payBill = new PayBill();
                payBill.setUserId(Long.valueOf(userID));
                payBill.setOut_trade_no(out_trade_no);
                payBill.setItemName(subject);
                //转换为分为单位的整数
                Double total_amount1 = Double.valueOf(total_amount);
                Long total_amount2 = Long.valueOf((long) (total_amount1 * 100));
                payBill.setTotal_amount(total_amount2);
                Double receipt_amount1 = Double.valueOf(receipt_amount);
                Long receipt_amount2 = Long.valueOf((long) (receipt_amount1 * 100));
                payBill.setReceipt_amount(receipt_amount2);
                payBill.setStatus(1);//设置支付状态为1-已支付
                payBill.setTrade_status(trade_status);
                payBill.setGmtCreat(creatTime);
                payBill.setGmtPayment(payTime);
                payBill.setSeller_id(seller_id);
                payBill.setBuyer_logon_id(buyer_logon_id);
                payBill.setBuyer_id(buyer_id);
                payBill.setApp_id(app_id);
                payBill.setTrade_no(trade_no);

                Boolean success = true;
                try {
                    success = payBillService.insertBill(payBill);
                }catch (Exception e){
                    success = false;
                    e.printStackTrace();
                }

                if(success){
                    String resStr = "success";
                    BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                    out.write(resStr.getBytes());
                    out.flush();
                    out.close();
                    System.out.println("订单保存成功");
                }
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //付款完成后，支付宝系统发送该交易状态通知
            }
            System.out.println("success");
        }else {//验证失败
            System.out.println("fail");

            //调试用，写文本函数记录程序运行情况是否正常
            //String sWord = AlipaySignature.getSignCheckContentV1(params);
            //AlipayConfig.logResult(sWord);
        }
    }

    /*
    * 下载指定日期的支付宝账单zip文件
    * */
    @PostMapping("/downloadurlQuery")
    public void downloadurlQuery(String date) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id,
                AlipayConfig.merchant_private_key, "json", "UTF-8",
                AlipayConfig.alipay_public_key, "RSA2");//获得初始化的AlipayClient
        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();//创建API对应的request类
        System.out.println("查询日期="+date);
        request.setBizContent("{" +
                "    \"bill_type\":\"trade\"," +
                //"    \"bill_date\":\"2020-08-27\"}"); //设置业务参数
                "    \"bill_date\":\""+date+"\"}"); //设置业务参数
        AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);//通过alipayClient调用API，获得对应的response类
        System.out.println(response.getBillDownloadUrl());
        //System.out.print(response.getbody());
        //根据response中的结果继续业务逻辑处理
        //将接口返回的对账单下载地址传入urlStr
        String urlStr = response.getBillDownloadUrl();
        if(urlStr == null || StringUtils.isBlank(urlStr)){
            System.out.println("该周期没有金额流水");
            return;
        }
        //指定希望保存的文件路径
        //String filePath = "E:\\fund_bill_20160405.zip";
        Date date1 = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String time = format.format(date1);
        String filePath = "E:\\bill\\"+date+".zip";
        //String filePath = "/yft/myProject/xtyl/paybill/"+date+".zip";
        URL url = null;
        HttpURLConnection httpUrlConnection = null;
        InputStream fis = null;
        FileOutputStream fos = null;
        try {
            url = new URL(urlStr);
            httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setConnectTimeout(5 * 1000);
            httpUrlConnection.setDoInput(true);
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setUseCaches(false);
            httpUrlConnection.setRequestMethod("GET");
            httpUrlConnection.setRequestProperty("Charsert", "UTF-8");
            httpUrlConnection.connect();
            fis = httpUrlConnection.getInputStream();
            byte[] temp = new byte[1024];
            int b;
            fos = new FileOutputStream(new File(filePath));
            while ((b = fis.read(temp)) != -1) {
                fos.write(temp, 0, b);
                fos.flush();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fis!=null) fis.close();
                if(fos!=null) fos.close();
                if(httpUrlConnection!=null) httpUrlConnection.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /*
    * 根据文件路径进行对账(下载支付宝订单zip，选择该文件)
    * */
    @PostMapping("/read")
    @ResponseBody
    public String readQuery(String filePath){
        String connet = "";
        try {

            ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(filePath)));
            ArchiveEntry zipFile;
            //获得输入流，文件为zip格式，
            //支付宝提供
            //20886126836996110156_20160906.csv.zip内包含
            //20886126836996110156_20160906_业务明细.csv
            //20886126836996110156_20160906_业务明细(汇总).csv
            File file = new File(filePath);
            ZipInputStream in = new ZipInputStream(new FileInputStream(file));
            //不解压直接读取,加上gbk解决乱码问题
            BufferedReader br = new BufferedReader(new InputStreamReader(zipArchiveInputStream,"GBK"));
            //ZipEntry zipFile;
            //返回的字符串---每个文件内容相加
            BufferedWriter bw = null;
            //循环读取zip中的cvs文件，无法使用jdk自带，因为文件名中有中文
            while ((zipFile=zipArchiveInputStream.getNextEntry())!=null) {
                if (zipFile.isDirectory()){
                    //如果是目录，不处理
                }
                String file_connet = "";
                //获得cvs名字
                String fileName = zipFile.getName();
                System.out.println("-----"+fileName);
                //检测文件是否存在
                if (fileName != null && fileName.indexOf(".") != -1) {
                    String line;
                    /*
                     * 1.每一行用 | 隔开
                     * 2.每一个文件用 ; 隔开
                     */
                    //  bw = new BufferedWriter(new FileWriter("d:\\test\\test.txt")); //测试读取内容
                    while ((line = br.readLine()) != null) {

                        file_connet = file_connet + "|" + line;
                        // System.out.println(line);

                    }
                }

                connet = connet + file_connet + ";";
            }
            //  bw.write(connet);
            //关闭流
            //  bw.close();
            br.close();
            in.close();
            Boolean isCheck = payBillService.checkPayBill(connet);
            if(isCheck){
                return "账单正常";
            }else {
                return "账单不正常";
            }
            /*System.out.println(connet);
            //文件根据；符号分隔为多个文件
            String[] filePath = connet.split(";");
            System.out.println("明细="+filePath[0]);
            System.out.println("汇总="+filePath[1]);
            //明细文件根据|分隔每一行数据
            String[] line = filePath[0].split("\\|");
            //获取每个订单的明细账单数据--从6开始因为读取的字符串中分隔后有一行为空，再除去固定的5行，剩下的都是订单行数据
            List<AliPayBill> aliPayBills = new ArrayList();
            for (int i=6;i<line.length-4;i++){
                //将每行数据根据，分隔每一个元素
                String[] title = line[i].split(",");
                //创建一个支付宝账单订单明细对象，存放支付宝中订单的数据
                AliPayBill aliPayBill = new AliPayBill();
                Reconciliation reconciliation = new Reconciliation();
                //0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
                for(int a=0;a<title.length;a++){
                    reconciliation.setAlipayTradeNo(title[0].trim());
                    aliPayBill.setAlipay_trade_no(title[0].trim());
                    reconciliation.setOutTradeNo(title[1].trim());
                    aliPayBill.setOut_trade_no(title[1].trim());
                    aliPayBill.setTrade_type(title[2].trim());
                    aliPayBill.setProject(title[3].trim());
                    aliPayBill.setGmtCreat(title[4].trim());
                    aliPayBill.setGmtPayment(title[5].trim());
                    reconciliation.setAlipayAmount(Double.valueOf(title[11].trim()));
                    aliPayBill.setTotal_amount(title[11].trim());
                    reconciliation.setMerchantsAmount(Double.valueOf(title[12].trim()));
                    aliPayBill.setReceipt_amount(title[12].trim());
                    aliPayBill.setRemarks(title[24].trim());
                }
                System.out.println("对账账单单个订单="+reconciliation);
                System.out.println("明细对象="+aliPayBill);
                aliPayBills.add(aliPayBill);
                System.out.println("每行订单数据="+line[i]);
            }
            //汇总文件根据|分隔每一行数据
            String[] line2 = filePath[1].split("\\|");
            //同理，从7开始因为分隔后有一个空元素
            String[] title2 = line2[7].split(",");
            System.out.println("订单总数="+title2[2].trim()+",合计金额="+title2[4].trim()+",实际商家收款金额="+title2[5].trim()+",实收净额="+title2[11].trim());
            AlipayTotalBill alipayTotalBill = new AlipayTotalBill();
            alipayTotalBill.setAlipayOrders(Long.valueOf(title2[2].trim()));
            alipayTotalBill.setAlipayTotaoAmount(Double.valueOf(title2[4].trim()));
            alipayTotalBill.setReceiptAmount(Double.valueOf(title2[5].trim()));
            String date = title2[1];
            boolean isCheck = this.checkTotalAmount(alipayTotalBill,date);*/


            /*String[] split = filePath[0].split(",");
            System.out.println("明细中的支付宝交易号="+split[25]);
            String[] split1 = filePath[1].split(",");
            System.out.println(split1[3]);*/

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("zip文件读取失敗" + e);
            //this.readQuery();
            return "false";
        }

        //return connet;
    }

    //支付宝订单查询
    @PostMapping("/query")
    @ResponseBody
    public void queryBill(String out_trade_no,String trade_no) throws AlipayApiException {
        /*String out_trade_no="159851102833013693176496092886";
        if(out_trade_no1 != null){
            out_trade_no=out_trade_no1;
        }
        String trade_no="2020082722001483301429636423";*/
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl,AlipayConfig.app_id,
                AlipayConfig.merchant_private_key,"json","UTF-8",
                AlipayConfig.alipay_public_key,"RSA2");
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        if(out_trade_no != null && trade_no == null){
            request.setBizContent("{" +
                    "\"out_trade_no\":\""+out_trade_no+"\"" +
                    "  }");
        }else if(trade_no != null && out_trade_no == null){
            request.setBizContent("{" +
                    "\"trade_no\":\""+trade_no+"\"" +
                    "  }");
        }else {
            request.setBizContent("{" +
                    "\"out_trade_no\":\""+out_trade_no+"\"," +
                    "\"trade_no\":\""+trade_no+"\"" +
                    "  }");
        }
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        String body = response.getBody();
        System.out.println("shangp="+response.getSubject());
        System.out.println("ext_infos="+response.getExtInfos());
        System.out.println("seller_id="+response.getAlipaySubMerchantId());
        String subCode = response.getSubCode();
        System.out.println("subCode:"+subCode);
        if("ACQ.SYSTEM_ERROR".equals(subCode)){
            System.out.println("系统错误");
        }else if("ACQ.INVALID_PARAMETER".equals(subCode)){
            System.out.println("参数无效");
        }else if("ACQ.TRADE_NOT_EXIST".equals(subCode)){
            System.out.println("查询订单不存在");
        }else {
            System.out.println("查询成功");
        }
        System.out.println("body="+body);
        System.out.println(response.isSuccess());
        if(response.isSuccess()){
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
    }


    //根据out_trade_no解析其中的手机号获取对应的用户id
    public Long getUserID(String out_trade_no){
        System.out.println("out_trade_no="+out_trade_no);
        String substring = out_trade_no.substring(13,24);
        System.out.println("substring="+substring);
        User byUsername = userService.findByUsername(substring);
        return byUsername.getId();
    }
    @Autowired
    private TestService testService;
    @PostMapping("/testpool")
    @ResponseBody
    @Async("asyncServiceExecutor")
    public AjaxResult testPool(){
        try {
            PayBill payBill = new PayBill();
            payBill.setOut_trade_no("555555555");
            payBill.setTrade_no("1516555");
            payBill.setUserId(56L);
            payBill.setItemName("222");
            payBill.setTotal_amount(20L);
            PayBill insert = testService.insert(payBill);
            AjaxResult ajaxResult = AjaxResult.me().setResultObj(insert);
            return ajaxResult;
        }catch (Exception e){
            return AjaxResult.me().setSuccess(false).setCode(ResponseCode.FAILURE.getCode());
        }
    }


}
